#include <stdio.h>
#include <stdlib.h>

#define NOME_ARQ_ENTRADA "in.ppm"
#define NOME_ARQ_SAIDA "out.ppm"

typedef struct
{
    int R;
    int G;
    int B;
} pixel;

typedef struct
{
    pixel M[8000][3000];//M[X][Y]
    int nColunas;//X maximo
    int nLinhas;//Y maximo
    int max;
} matrizPixel;




int abreArquivo( FILE **arq )
{
    *arq = fopen( NOME_ARQ_ENTRADA, "r" );
    if( arq == NULL )
        return 0;
    return 1;
}

void geraArqSaida( matrizPixel *mp )
{
    
    FILE *arq = fopen( NOME_ARQ_SAIDA, "w+" );
    int i, j;

    fprintf(arq,"P3 %d %d %d\n",(*mp).nColunas, (*mp).nLinhas,(*mp).max);

    for( i = 0; i < (*mp).nLinhas; i++)
    {
        for( j = 0; j < (*mp).nColunas; j++ )
        {
           fprintf(arq,"%d %d %d\n", (*mp).M[i][j].R, (*mp).M[i][j].G, (*mp).M[i][j].B );
        }
    }
    fclose(arq);
}

void geraMatrizImagem( FILE * arqImg, matrizPixel * mp)
{
    int i, j;

    fscanf( arqImg, "%*s %d %d %d", &(*mp).nColunas, &(*mp).nLinhas, &(*mp).max);
    // printf( "P3 %d %d %d\n", mp.nColunas, mp.nLinhas, mp.max);
    

    //%*s: Pula o P3

    for( i = 0; i < (*mp).nLinhas; i++)
    {
        for( j = 0; j < (*mp).nColunas; j++ )
        {
            fscanf( arqImg, "%d%d%d", &(*mp).M[i][j].R, &(*mp).M[i][j].G, &(*mp).M[i][j].B );
            // printf("%d %d %d\n", mp.M[i][j].R, mp.M[i][j].G, mp.M[i][j].B );
        }
    }
}

pixel smooth( matrizPixel *mp, int x, int y )
{
    pixel resultado;
    int somatoriaR = 0, somatoriaG = 0, somatoriaB = 0;
    int i, j;

    //Smooth efetuado em grupo 5x5 de pixels
    for( i = x - 2; i <= x + 2; i++ )
    {
        for( j = y - 2; j <= y + 2; j++ )
        {

            if( i >= 0 && i < mp->nLinhas && j >= 0 && j < mp->nColunas )
            {
                /*Se a posicao existir na matriz, seus componentes sao
                adicionados na somatoria, caso contrario, eh assumido que
                seus componentes sao zerados, e entao nada sera feito*/
                somatoriaR += mp->M[i][j].R;
                somatoriaG += mp->M[i][j].G;
                somatoriaB += mp->M[i][j].B;
            }
        }
    }

    resultado.R = somatoriaR / 25;
    resultado.G = somatoriaG / 25;
    resultado.B = somatoriaB / 25;

    return resultado;
}

void smoothMatriz( matrizPixel *mp,matrizPixel *mps )
{
    int i, j;
    (*mps).nColunas = (*mp).nColunas;
    (*mps).nLinhas = (*mp).nLinhas;
    (*mps).max = (*mp).max;

    for( i = 0; i < (*mps).nLinhas; i++)
        for( j = 0; j < (*mps).nColunas; j++)
           (*mps).M[i][j] = smooth( mp, i, j );
}


int main()
{
    FILE *arq;
    matrizPixel * mp,  *mps;   
    mp = (matrizPixel*) malloc (sizeof(matrizPixel));
    mps = (matrizPixel*) malloc (sizeof(matrizPixel));
    
    if( !abreArquivo( &arq ) ){
        printf("Arquivo nao encontrado");
        return 0;
    }

    geraMatrizImagem( arq, mp );

    struct timeval time1,time2; 
    gettimeofday(&time1,NULL);

    smoothMatriz( mp, mps );
    
    gettimeofday(&time2,NULL);
    printf("elapsed = %lfs\n",(double)(time2.tv_sec - time1.tv_sec));

    geraArqSaida( mps );

    free(mp);
    free(mps);
    fclose( arq );

    return 1;
}
